/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#ifndef __VPASS_H__
#define __VPASS_H__

#include "./vTextureUnit.h"
#include "./vColor.h"
#include "../../Macros/vMemoryMacros.h"

namespace Vendetta {
	/*! \class vPass
	 *  \brief A vPass class represents single render pass while rendering objects.
	 *
	 *	Passes are used by vMaterial for creating effects requiring multipass rendering
	 *	or single rendering. If no texture is assigned then at first rendering attempt
	 *	engine will crash.
	 *
	 *	\sa vMaterial.
	 */
	class vPass {
		friend class vMaterial;
		friend class vMaterialParser;
	public:		
		/*! \brief Enables/Disables lighting.
		 *
		 *	Sets whether material should receive light or not. Lighting is enabled by default.
		 *			 
		 *  \param		bEnabled			True if lighting should be enabled, false otherwise.
		 */
		vVoid SetLighting(vBool bEnabled);

		/*! \brief Sets ambient color.
		 *
		 *	Default ambient color is (0.5, 0.5, 0.5).
		 *			 
		 *  \param		color				Ambient color to set.
		 *	\sa			vColor.
		 */
		vVoid SetAmbient(const vColor& color);

		/*! \brief Sets diffuse color.
		 *
		 *	Default diffuse color is (0.5, 0.5, 0.5).
		 *			 
		 *  \param		color				Diffuse color to set.
		 *	\sa			vColor.
		 */
		vVoid SetDiffuse(const vColor& color);

		/*! \brief Sets specular color and factor.
		 *
		 *	Default specular color is (0.0, 0.0, 0.0) and is disabled. If factor < 0 then specular
		 *	light component is not set.
		 *			 
		 *  \param		color				Specular color to set.
		 *  \param		rFactor				Specular factor to set.
		 *	\sa			vColor.
		 */
		vVoid SetSpecular(const vColor& color, vReal rFactor);

		/*! \brief Sets emissive color.
		 *
		 *	Default emissive color is (0.0, 0.0, 0.0). If color is (0.0, 0.0, 0.0) emissive is disabled.
		 *			 
		 *  \param		color				Emissive color to set.
		 *	\sa			vColor.
		 */
		vVoid SetEmissive(const vColor& color);

	protected:
		/*! \brief Constructor.
		 *
		 */
		vPass();

		/*! \brief Copy constructor. Nothing happens.
		 *
		 */
		vPass(const vPass& pass);

		/*! \brief Destructor.
		 *
		 */
		virtual ~vPass();
		
		/*! \brief Assign operator. Nothing happens.
		 *
		 */
		vPass& operator=(const vPass& pass);

		/*! \brief Adds texture unit.
		 *
		 *	Pass doesn't have to have any texture units.
		 *			 
		 *  \param		*unit				Texture unit to add.
		 *	\sa			vTextureUnit.
		 */
		vVoid addTextureUnit(vTextureUnit* unit);

		/*! \brief Creates texture unit.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		minMagFilterMode		Filter mode.
		 *  \param		rRotateAngle			Rotate angle in degrees.
		 *  \param		rXScale					X dimension scale factor.
		 *  \param		rYScale					Y dimension scale factor.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 *	\sa			vTextureUnit::minMagFilterMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTextureUnit::eFilterMode minMagFilterMode, vReal rRotateAngle, vReal rXScale, 
			vReal rYScale, vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		minMagFilterMode		Filter mode.
		 *  \param		rRotateAngle			Rotate angle in degrees.
		 *  \param		rXYScale				X, Y dimensions scale factor.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 *	\sa			vTextureUnit::minMagFilterMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTextureUnit::eFilterMode minMagFilterMode, vReal rRotateAngle, vReal rXYScale, 
			vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		minMagFilterMode		Filter mode.
		 *  \param		rRotateAngle			Rotate angle in degrees.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 *	\sa			vTextureUnit::minMagFilterMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTextureUnit::eFilterMode minMagFilterMode, vReal rRotateAngle, vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		minMagFilterMode		Filter mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 *	\sa			vTextureUnit::minMagFilterMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTextureUnit::eFilterMode minMagFilterMode, vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 *	\sa			vTextureUnit::minMagFilterMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		uvwAddressMode			U, V, W parameters address mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTextureUnit::eAddressMode uvwAddressMode, 
			vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		uAddressMode			U parameter address mode.
		 *  \param		vAddressMode			V parameter address mode.
		 *  \param		wAddressMode			W parameter address mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vTextureUnit* createTextureUnit(vTextureUnit::eAddressMode uAddressMode, 
			vTextureUnit::eAddressMode vAddressMode, vTextureUnit::eAddressMode wAddressMode, 
			vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		bBlendingOn				Sets whether texture unit should blended.
		 *  \param		srcBlendMode			Source target blend mode.
		 *  \param		dstBlendMode			Destination target blend mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eBlendMode.
		 */
		vTextureUnit* createTextureUnit(vBool bBlendingOn, vTextureUnit::eBlendMode srcBlendMode, 
			vTextureUnit::eBlendMode dstBlendMode, vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		uvwAddressMode			U, V, W parameters address mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eAddressMode.
		 */
		vTextureUnit* createTextureUnit(vTextureUnit::eAddressMode uvwAddressMode, vTexture* pTexture);

		/*! \brief Creates texture unit. Overloaded.
		 *
		 *  \param		minMagFilterMode		Filter mode.
		 *  \param		*pTexture				Ptr to texture (mustn't be null).
		 *	\sa			vTextureUnit.
		 *	\sa			vTextureUnit::eFilterMode.
		 */
		vTextureUnit* createTextureUnit(vTextureUnit::eFilterMode minMagFilterMode, vTexture* pTexture);

		/*! \brief Creates texture unit.
		 *
		 *  \param		*pTexture				Ptr to texture (mustn't be null). Default is null.
		 *  \param		rRotateAngle			Rotate angle in degrees, default 0.0.
		 *  \param		rXScale					X dimension scale factor, default 1.0.
		 *  \param		rYScale					Y dimension scale factor, default 1.0.
		 *	\sa			vTextureUnit.
		 */
		vTextureUnit* createTextureUnit(vTexture* pTexture = vNull, vReal rRotateAngle = 0.0, 
			vReal rXScale = 1.0, vReal rYScale = 1.0);

	private:
		vBool mLightingOn;
		vColor mAmbient;
		vColor mDiffuse;
		vColor mSpecular;
		vColor mEmissive;
		vReal mSpecularFactor;
		vArray<vTextureUnit*> mTextureUnits;
	};
}

#endif // __VPASS_H__